package com.shayu.aicodemother.core;


import cn.hutool.json.JSONUtil;
import com.shayu.aicodemother.ai.AiCodeGeneratorService;
import com.shayu.aicodemother.ai.AiCodeGeneratorServiceFactory;
import com.shayu.aicodemother.ai.model.HtmlCodeResult;
import com.shayu.aicodemother.ai.model.MultiFileCodeResult;
import com.shayu.aicodemother.ai.model.message.AiResponseMessage;
import com.shayu.aicodemother.ai.model.message.ToolExecutedMessage;
import com.shayu.aicodemother.ai.model.message.ToolRequestMessage;
import com.shayu.aicodemother.core.parser.CodeParserExecutor;
import com.shayu.aicodemother.core.saver.CodeFileSaverExecutor;
import com.shayu.aicodemother.exception.BusinessException;
import com.shayu.aicodemother.exception.ErrorCode;
import com.shayu.aicodemother.model.enums.CodeGenTypeEnum;
import dev.langchain4j.model.chat.response.ChatResponse;
import dev.langchain4j.service.TokenStream;
import dev.langchain4j.service.tool.ToolExecution;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;

import java.io.File;

@Service
@Slf4j
public class AiCodeGeneratorFacade {


    @Resource
    private AiCodeGeneratorServiceFactory aiCodeGeneratorServiceFactory;


    /**
     * 门面模式
     * 统一入口：根据类型生成并保存代码
     *
     * @param userMessage     用户提示词
     * @param codeGenTypeEnum 生成类型
     * @return
     */
    public File generateAndSaveCode(String userMessage, CodeGenTypeEnum codeGenTypeEnum,Long appid) {

        if (codeGenTypeEnum == null) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "生成类型为空");
        }
        AiCodeGeneratorService aiCodeGeneratorService = aiCodeGeneratorServiceFactory.getAiCodeGeneratorService(appid);
        return switch (codeGenTypeEnum) {
            case HTML -> {
                HtmlCodeResult result = aiCodeGeneratorService.generatorHtmlCode(userMessage);
                yield  CodeFileSaverExecutor.executeSaver(codeGenTypeEnum,result,appid);
            }
            case MULTI_FILE -> {
                MultiFileCodeResult result = aiCodeGeneratorService.generatorMultiFileCoe(userMessage);
                yield  CodeFileSaverExecutor.executeSaver(codeGenTypeEnum,result,appid);
            }
            default -> {

                String errorMessage = "不支持的生成类型:" + codeGenTypeEnum.getValue();
                throw new BusinessException(ErrorCode.SYSTEM_ERROR, errorMessage);
            }
        };

    }

    /**
     * 门面模式
     * 统一入口：根据类型生成并保存代码(流式)
     *
     * @param userMessage     用户提示词
     * @param codeGenTypeEnum 生成类型
     * @return
     */
    public Flux<String> generateAndSaveCodeStream(String userMessage, CodeGenTypeEnum codeGenTypeEnum,Long appid) {

        if (codeGenTypeEnum == null) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "生成类型为空");
        }
        AiCodeGeneratorService aiCodeGeneratorService = aiCodeGeneratorServiceFactory.getAiCodeGeneratorService(appid,codeGenTypeEnum);
        return switch (codeGenTypeEnum) {
            case HTML -> {
                Flux<String> stringFlux = aiCodeGeneratorService.generateHtmlCodeStream(userMessage);
                yield processCodeStream(stringFlux, CodeGenTypeEnum.HTML,appid);
            }
            case MULTI_FILE -> {
                Flux<String> stringFlux = aiCodeGeneratorService.generateMultiFileCodeStream(userMessage);
                yield processCodeStream(stringFlux, CodeGenTypeEnum.MULTI_FILE,appid);
            }
            case VUE_PROJECT -> {
                TokenStream tokenStream = aiCodeGeneratorService.generateVueProjectCodeStream(appid, userMessage);
                yield processTokenStream(tokenStream);
            }
            default -> {

                String errorMessage = "不支持的生成类型:" + codeGenTypeEnum.getValue();
                throw new BusinessException(ErrorCode.SYSTEM_ERROR, errorMessage);
            }
        };

    }

    /**
     * 将 TokenStream 转换为 Flux<String>，并传递工具调用信息
     *
     * @param tokenStream TokenStream 对象
     * @return Flux<String> 流式响应
     */
    private Flux<String> processTokenStream(TokenStream tokenStream) {
        return Flux.create(sink -> {
            tokenStream.onPartialResponse((String partialResponse) -> {
                        AiResponseMessage aiResponseMessage = new AiResponseMessage(partialResponse);
                        sink.next(JSONUtil.toJsonStr(aiResponseMessage));
                    })
                    .onPartialToolExecutionRequest((index, toolExecutionRequest) -> {
                        ToolRequestMessage toolRequestMessage = new ToolRequestMessage(toolExecutionRequest);
                        sink.next(JSONUtil.toJsonStr(toolRequestMessage));
                    })
                    .onToolExecuted((ToolExecution toolExecution) -> {
                        ToolExecutedMessage toolExecutedMessage = new ToolExecutedMessage(toolExecution);
                        sink.next(JSONUtil.toJsonStr(toolExecutedMessage));
                    })
                    .onCompleteResponse((ChatResponse response) -> {
                        sink.complete();
                    })
                    .onError((Throwable error) -> {
                        error.printStackTrace();
                        sink.error(error);
                    })
                    .start();
        });
    }



    /**
     * 通用流式代码处理方法
     *
     * @param htmlCodeStream
     * @param codeGenTypeEnum 代码生成类型
     * @return
     */
    private Flux<String> processCodeStream(Flux<String> htmlCodeStream, CodeGenTypeEnum codeGenTypeEnum,Long appid) {

        StringBuilder stringBuilder = new StringBuilder();
        return htmlCodeStream.doOnNext(chunk -> {
            //将流中的代码拼接
            stringBuilder.append(chunk);
        }).doOnComplete(
                //流式返回并保存代码
                () -> {
                    try {
                        String stringCode = stringBuilder.toString();
                        //使用执行器解析代码
                        Object object = CodeParserExecutor.executeParser(stringCode, codeGenTypeEnum);
                        //使用执行器保存代码
                        File file = CodeFileSaverExecutor.executeSaver(codeGenTypeEnum, object,appid);
                        log.info("保存文件，路径为：{}", file.getAbsolutePath());
                    } catch (Exception e) {
                        log.error("保存失败，{}", e.getMessage());
                    }
                });

    }


    /**
     * 生成HTML模式的代码并保存（流式）
     *
     * @param userMessage
     * @return
     */
//    private Flux<String> generateAndSaveHtmlCodeStream(String userMessage) {
//
//        Flux<String> htmlCodeStream = aiCodeGeneratorService.generateHtmlCodeStream(userMessage);
//        StringBuilder stringBuilder = new StringBuilder();
//        return htmlCodeStream.doOnNext(chunk -> {
//            //将流中的代码拼接
//            stringBuilder.append(chunk);
//        }).doOnComplete(
//                //流式返回并保存代码
//                () -> {
//                    try {
//                        String stringCode = stringBuilder.toString();
//                        HtmlCodeResult result = CodeParser.parseHtmlCode(stringCode);
//                        File fileDir = CodeFileSaver.saveHtmlCodeResult(result);
//                        log.info("保存文件，路径为：{}", fileDir);
//                    } catch (Exception e) {
//                        log.error("保存失败，{}", e.getMessage());
//                    }
//                });
//
//    }


    /**
     * 生成多文件模式的代码并保存(流式)
     *
     * @param userMessage
     * @return保存的目录
     */
//    private Flux<String> generateAndSaveMultiFileCodeStram(String userMessage) {
//        Flux<String> stringFlux = aiCodeGeneratorService.generateMultiFileCodeStream(userMessage);
//        StringBuilder stringBuilder = new StringBuilder();
//        return stringFlux.doOnNext(chunk -> {
//            stringBuilder.append(chunk);
//        }).doOnComplete(() -> {
//            try {
//                String string = stringBuilder.toString();
//                MultiFileCodeResult multiFileCodeResult = CodeParser.parseMultiFileCode(string);
//                File fileDir = CodeFileSaver.saveMultiFileCodeResult(multiFileCodeResult);
//                log.info("保存文件，路径为：{}", fileDir);
//            } catch (Exception e) {
//                log.error("保存失败，{}", e.getMessage());
//            }
//
//        });
//    }

    /**
     * 生成多文件模式的代码并保存
     *
     * @param userMessage
     * @return保存的目录
     */
//    private File generateAndSaveMultiFileCode(String userMessage) {
//        MultiFileCodeResult result = aiCodeGeneratorService.generatorMultiFileCoe(userMessage);
//        return CodeFileSaver.saveMultiFileCodeResult(result);
//
//    }


    /**
     * 生成HTML模式的代码并保存
     *
     * @param userMessage
     * @return
     */
//    private File generateAndSaveHtmlCode(String userMessage) {
//
//        HtmlCodeResult result = aiCodeGeneratorService.generatorHtmlCode(userMessage);
//        return CodeFileSaver.saveHtmlCodeResult(result);
//
//    }


}
